﻿using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace MusicStore.Silverlight.Infrastructure
{
	using System;
	using System.Text;
	using System.Windows.Threading;
	using System.Xml;

   /// <summary>
   /// interface for a generic dispatcher
   /// </summary>
   public interface IDispatcher
   {
      Dispatcher Dispatcher { get; }

      void Run(Action a);

      void Run(Delegate d, params object[] args);
   }

	public static class UiDispatcher
	{
		public static void SetDispatcher(IDispatcher dispatcher)
		{
			Dispatcher = dispatcher;
		}

		private static IDispatcher Dispatcher = new InvokeDispatcher();

		public static void Run(Action a)
		{
			// EnsureDispatcher();
			Dispatcher.Run(a);
		}

		public static void Run(Delegate d, params object[] args)
		{
			// EnsureDispatcher();
			Dispatcher.Run(d, args);
		}

		private static void EnsureDispatcher()
		{
			if (Dispatcher == null)
				throw new ArgumentNullException("", "Call UiThread.SetDispatcher() during the application initialization passing in a UiDispatcher or an Dispatcher object");
		}
	}

	/// <summary>
	/// used on the UI projects to let the UI binding works when the properties are
	/// changed by background threads.
	/// </summary>
	public class WindowsDispatcher : IDispatcher
	{
		public WindowsDispatcher(Dispatcher dispatcher)
		{
			Dispatcher = dispatcher;
		}

		public Dispatcher Dispatcher { get; private set; }

		public void Run(Action a)
		{
			Dispatcher.BeginInvoke(a);
		}

		public void Run(Delegate d, params object[] args)
		{
			Dispatcher.BeginInvoke(d, args);
		}
	}

	/// <summary>
	/// used on the test classes
	/// </summary>
	public class InvokeDispatcher : IDispatcher
	{
		public Dispatcher Dispatcher
		{
			get { return null; }
		}

		public void Run(Action a)
		{
			a.Invoke();
		}

		public void Run(Delegate d, params object[] args)
		{
			d.DynamicInvoke(args);
		}
	}
}
